package com.aiserver.service.impl;

import com.aiserver.dto.LoginRequest;
import com.aiserver.dto.LoginResponse;
import com.aiserver.entity.User;
import com.aiserver.mapper.UserMapper;
import com.aiserver.service.AuthService;
import com.aiserver.service.SmsService;
import com.aiserver.service.WechatService;
import com.aiserver.util.CaptchaUtil;
import com.aiserver.util.EncryptUtil;
import com.aiserver.util.JwtUtil;
import com.aiserver.util.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 认证服务实现类
 */
@Service
public class AuthServiceImpl implements AuthService {

    private static final Logger logger = LoggerFactory.getLogger(AuthServiceImpl.class);

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private WechatService wechatService;

    @Autowired
    private SmsService smsService;

    @Value("${app.security.max-login-attempts}")
    private Integer maxLoginAttempts;

    @Value("${app.security.lock-time}")
    private Integer lockTime;

    @Value("${app.captcha.expire-time}")
    private Integer captchaExpireTime;

    @Override
    public LoginResponse login(LoginRequest request) {
        String username = request.getUsername();
        String password = request.getPassword();

        // 检查用户是否被锁定
        if (isUserLocked(username)) {
            throw new RuntimeException("账户已被锁定，请稍后再试");
        }

        // 验证图片验证码（如果提供）
        if (StringUtils.hasText(request.getCaptchaKey()) && StringUtils.hasText(request.getCaptcha())) {
            if (!verifyCaptcha(request.getCaptchaKey(), request.getCaptcha())) {
                throw new RuntimeException("验证码错误");
            }
        }

        // 查询用户
        User user = userMapper.findByUsername(username);
        if (user == null) {
            handleLoginFailure(username);
            throw new RuntimeException("用户名或密码错误");
        }

        // 验证密码
        String encryptedPassword = EncryptUtil.md5Encrypt(password);
        if (!encryptedPassword.equals(user.getPassword())) {
            handleLoginFailure(username);
            throw new RuntimeException("用户名或密码错误");
        }

        // 检查用户状态
        if (user.getStatus() != 1) {
            throw new RuntimeException("账户已被禁用");
        }

        // 登录成功处理
        handleLoginSuccess(username);

        // 生成token
        String token = jwtUtil.generateToken(user.getId(), user.getUsername());
        String refreshToken = jwtUtil.generateRefreshToken(user.getId(), user.getUsername());

        LoginResponse response = new LoginResponse(token, refreshToken, user.getId(), user.getUsername());
        response.setNickname(user.getNickname());
        response.setAvatar(user.getAvatar());

        logger.info("用户登录成功: {}", username);
        return response;
    }

    @Override
    public LoginResponse smsLogin(String phone, String code) {
        // 验证短信验证码
        String cachedCode = redisUtil.getCaptcha("sms:" + phone);
        if (!code.equals(cachedCode)) {
            throw new RuntimeException("验证码错误或已过期");
        }

        // 查询用户
        User user = userMapper.findByPhone(phone);
        if (user == null) {
            // 自动注册新用户
            user = new User();
            user.setPhone(phone);
            user.setUsername(phone);
            user.setNickname("用户" + phone.substring(phone.length() - 4));
            user.setStatus(1);
            user.setLoginFailCount(0);
            user.setCreateTime(LocalDateTime.now());
            user.setUpdateTime(LocalDateTime.now());
            userMapper.insert(user);
        }

        // 检查用户状态
        if (user.getStatus() != 1) {
            throw new RuntimeException("账户已被禁用");
        }

        // 删除验证码
        redisUtil.deleteCaptcha("sms:" + phone);

        // 生成token
        String token = jwtUtil.generateToken(user.getId(), user.getUsername());
        String refreshToken = jwtUtil.generateRefreshToken(user.getId(), user.getUsername());

        LoginResponse response = new LoginResponse(token, refreshToken, user.getId(), user.getUsername());
        response.setNickname(user.getNickname());
        response.setAvatar(user.getAvatar());

        logger.info("用户短信登录成功: {}", phone);
        return response;
    }

    @Override
    public LoginResponse wechatLogin(String code, String state) {
        try {
            // 通过微信服务获取用户信息
            User wechatUser = wechatService.getUserInfoByCode(code);
            
            // 查询是否已存在用户
            User user = userMapper.findByWechatOpenId(wechatUser.getWechatOpenId());
            
            if (user == null) {
                // 自动注册新用户
                user = new User();
                user.setWechatOpenId(wechatUser.getWechatOpenId());
                user.setWechatUnionId(wechatUser.getWechatUnionId());
                user.setNickname(wechatUser.getNickname());
                user.setAvatar(wechatUser.getAvatar());
                user.setUsername("wx_" + wechatUser.getWechatOpenId().substring(0, 8));
                user.setStatus(1);
                user.setLoginFailCount(0);
                user.setCreateTime(LocalDateTime.now());
                user.setUpdateTime(LocalDateTime.now());
                userMapper.insert(user);
            } else {
                // 更新用户信息
                user.setNickname(wechatUser.getNickname());
                user.setAvatar(wechatUser.getAvatar());
                user.setUpdateTime(LocalDateTime.now());
                userMapper.update(user);
            }

            // 检查用户状态
            if (user.getStatus() != 1) {
                throw new RuntimeException("账户已被禁用");
            }

            // 生成token
            String token = jwtUtil.generateToken(user.getId(), user.getUsername());
            String refreshToken = jwtUtil.generateRefreshToken(user.getId(), user.getUsername());

            LoginResponse response = new LoginResponse(token, refreshToken, user.getId(), user.getUsername());
            response.setNickname(user.getNickname());
            response.setAvatar(user.getAvatar());

            logger.info("用户微信登录成功: {}", user.getUsername());
            return response;
        } catch (Exception e) {
            logger.error("微信登录失败", e);
            throw new RuntimeException("微信登录失败: " + e.getMessage());
        }
    }

    @Override
    public LoginResponse refreshToken(String refreshToken) {
        if (!jwtUtil.isValidToken(refreshToken)) {
            throw new RuntimeException("刷新token无效");
        }

        String tokenType = jwtUtil.getTokenType(refreshToken);
        if (!"refresh".equals(tokenType)) {
            throw new RuntimeException("token类型错误");
        }

        if (jwtUtil.isTokenExpired(refreshToken)) {
            throw new RuntimeException("刷新token已过期");
        }

        // 检查token是否在黑名单中
        if (redisUtil.isTokenInBlacklist(refreshToken)) {
            throw new RuntimeException("token已失效");
        }

        Long userId = jwtUtil.getUserIdFromToken(refreshToken);
        String username = jwtUtil.getUsernameFromToken(refreshToken);

        // 生成新的token
        String newToken = jwtUtil.generateToken(userId, username);
        String newRefreshToken = jwtUtil.generateRefreshToken(userId, username);

        // 将旧的刷新token加入黑名单
        redisUtil.addTokenToBlacklist(refreshToken, jwtUtil.getExpirationDateFromToken(refreshToken).getTime());

        LoginResponse response = new LoginResponse(newToken, newRefreshToken, userId, username);
        
        // 获取用户信息
        User user = userMapper.findById(userId);
        if (user != null) {
            response.setNickname(user.getNickname());
            response.setAvatar(user.getAvatar());
        }

        return response;
    }

    @Override
    public void logout(String token) {
        if (jwtUtil.isValidToken(token)) {
            // 将token加入黑名单
            redisUtil.addTokenToBlacklist(token, jwtUtil.getExpirationDateFromToken(token).getTime());
            logger.info("用户登出成功");
        }
    }

    @Override
    public void sendSmsCode(String phone) {
        // 生成6位数字验证码
        String code = String.format("%06d", new Random().nextInt(999999));
        // 存储到Redis，5分钟过期
        redisUtil.setCaptcha("sms:" + phone, code, captchaExpireTime);
        // 这里应该调用实际的短信服务
         smsService.sendCode(phone, code);
    }

    @Override
    public String generateCaptcha(String key) {
        // 生成4位随机验证码
        String code = CaptchaUtil.generateRandomCode(4);
        // 存储到Redis，5分钟过期
        redisUtil.setCaptcha(key, code, captchaExpireTime);
        // 生成验证码图片并返回base64编码
        return CaptchaUtil.generateCaptchaImage(code);
    }

    @Override
    public boolean verifyCaptcha(String key, String code) {
        String cachedCode = redisUtil.getCaptcha(key);
        if (code.equals(cachedCode)) {
            redisUtil.deleteCaptcha(key);
            return true;
        }
        return false;
    }

    @Override
    public User register(String username, String password, String phone) {
        // 检查用户名是否已存在
        if (userMapper.countByUsername(username) > 0) {
            throw new RuntimeException("用户名已存在");
        }

        // 检查手机号是否已存在
        if (StringUtils.hasText(phone) && userMapper.countByPhone(phone) > 0) {
            throw new RuntimeException("手机号已被注册");
        }

        // 创建新用户
        User user = new User();
        user.setUsername(username);
        user.setPassword(EncryptUtil.md5Encrypt(password));
        user.setPhone(phone);
        user.setNickname(username);
        user.setStatus(1);
        user.setLoginFailCount(0);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());

        userMapper.insert(user);
        logger.info("用户注册成功: {}", username);
        return user;
    }

    @Override
    public boolean isUserLocked(String username) {
        Long failCount = redisUtil.getLoginFailCount(username);
        return failCount >= maxLoginAttempts;
    }

    @Override
    public void handleLoginFailure(String username) {
        Long failCount = redisUtil.incrementLoginFailCount(username);
        logger.warn("用户 {} 登录失败，失败次数: {}", username, failCount);
        
        if (failCount >= maxLoginAttempts) {
            logger.warn("用户 {} 登录失败次数过多，账户已被锁定", username);
        }
    }

    @Override
    public void handleLoginSuccess(String username) {
        redisUtil.clearLoginFailCount(username);
        logger.info("用户 {} 登录成功，清除失败计数", username);
    }
}